package lumis.util.security.acl.serialization;

import java.util.List;

import lumis.portal.PortalException;
import lumis.portal.group.GroupConfig;
import lumis.portal.serialization.DeserializationContext;
import lumis.portal.serialization.SerializationException;
import lumis.portal.serialization.operation.ConfigDependencyAnalyzer;
import lumis.portal.serialization.operation.ConfigForeignKey;
import lumis.portal.serialization.operation.ConfigPersistence;
import lumis.portal.serialization.operation.IConfigPersister;
import lumis.util.security.acl.AccessControlEntry;
import lumis.util.security.acl.AccessControlList;
import lumis.util.security.acl.Permissions;

/**
 * Responsible for analyze foreign key dependencies of a ACL being deserialized.
 *
 * @version $Revision: 6880 $ $Date: 2007-05-16 16:41:21 -0300 (Wed, 16 May 2007) $
 * @since 4.0.9
 */
public class AclDependencyAnalyzer extends ConfigDependencyAnalyzer<AccessControlList>
{
	protected final List<ConfigForeignKey> entryForeignKeys;

	public AclDependencyAnalyzer(DeserializationContext deserializationContext, List<ConfigForeignKey> aclForeignKeys, List<ConfigForeignKey> aclEntryForeignKeys, AccessControlList originalConfig)
	{
		super(deserializationContext, aclForeignKeys, originalConfig);
		this.entryForeignKeys = aclEntryForeignKeys;
	}

	@Override
	public void analyze(IConfigPersister configPersister)
	{
		super.analyze(configPersister);

		// if there is any entry that depends on a not yet deserialized principal, replace all entries with an entry that gives full permission to "all users" group
		AccessControlEntry tempEntry = null;
		for (AccessControlEntry entry : originalConfig.getEntries())
		{
			ConfigDependencyAnalyzer<AccessControlEntry> entryDependencyAnalyzer = new ConfigDependencyAnalyzer<AccessControlEntry>(deserializationContext, entryForeignKeys, entry);
			entryDependencyAnalyzer.analyze(null);
			if (entryDependencyAnalyzer.getHasViolation() && configPersister != null)
			{
				deserializationContext.getDependentConfigPersistences().addDependentConfigOperation(entryDependencyAnalyzer.getDependencyKeys(), new ConfigPersistence(originalConfig, configPersister));
				if (tempEntry == null)
					tempEntry = new AccessControlEntry(GroupConfig.GROUP_ALL_USERS_ID, new Permissions(Integer.MAX_VALUE, 0,0,0), false);
			}
		}
		persistableConfig = new AccessControlList(persistableConfig.getId(), tempEntry != null ? new AccessControlEntry[] {tempEntry} : originalConfig.getEntries(), persistableConfig.isInheriting(), persistableConfig.getParentId());
	}

	@Override
	public boolean foreignKeysExists()
	{
		boolean checked = super.foreignKeysExists();
		if (!checked) 
			return false;
		for (AccessControlEntry entry : originalConfig.getEntries())
			if (!(new ConfigDependencyAnalyzer<AccessControlEntry>(deserializationContext, entryForeignKeys, entry).foreignKeysExists()))
				return false;
		return true;
	}

	
	@Override
	public AccessControlList getMappedPersistableConfig()
	{
		AccessControlList mappedAccessControlList = super.getMappedPersistableConfig();
		try
		{
			for (AccessControlEntry entry : mappedAccessControlList.getEntries())
				deserializationContext.applyForeignKeyFieldIdMappings(entry, entryForeignKeys);
		}
		catch (SerializationException e)
		{
			throw new IllegalStateException(e);
		}
		return mappedAccessControlList;
	}
}
